package com.pafcio.sudoku;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public class SudokuSolver {

	Board board;
	
	public Board solve(final Board inputBoard) {
		
		board = new Board(inputBoard);
		
		if(board.isOK()){
			return board;
		}
		
		solveOneMissingCellInRow();
		solveOneMissingCellInColumn();
		solveIfOnlyOneValueIsAllowed();
		
		return board;
	}

	private void solveOneMissingCellInRow() {
		for(int r=0; r<9; r++){
			Vector row = board.getRow(r);
			Set<Integer> missingValues = row.getMissingValues();
			if(missingValues.size() == 1){
				Set<Integer> missingIndexes = row.getMissingIndexes();
				Integer col = missingIndexes.toArray(new Integer[0])[0];
				Integer value = missingValues.toArray(new Integer[0])[0];
				board.setValueAt(r, col, value);			
			}
		}
	}
	
	private void solveOneMissingCellInColumn() {
		for(int col=0; col<9; col++){
			Vector column = board.getColumn(col);
			Set<Integer> missingValues = column.getMissingValues();
			if(missingValues.size() == 1){
				Set<Integer> missingIndexes = column.getMissingIndexes();
				Integer row = missingIndexes.toArray(new Integer[0])[0];
				Integer value = missingValues.toArray(new Integer[0])[0];
				board.setValueAt(row, col, value);
			}
		}
	}

	private void solveIfOnlyOneValueIsAllowed() {
		for(int row=0; row<1; row++){
			for(int col=0; col<1; col++){				
				Area area = board.getAreaFor(row, col);
				Set<Integer> missingValues = area.getMissingValues();
				if(missingValues.size() == 1){
					Set<Integer> missingIndexes = area.getMissingIndexes();
					Integer index = missingIndexes.toArray(new Integer[0])[0];
					Integer value = missingValues.toArray(new Integer[0])[0];
					area.setValueAt(row, col, value);
				}
			}
		}
	}

	private List<Proposition> getStepsFor(int row, int col) {
		List<Proposition> result = new ArrayList<Proposition>();
		
		for(int i=1; i<=9; i++){
			boolean numberAllowed = isNumberAllowedFor(i, row, col);
			if(numberAllowed){
				Proposition newProposition = new Proposition(i);
				result.add(newProposition);
			}
		}
		
		return result;
	}

	private boolean isNumberAllowedFor(int i, int rowNumber, int colNumber) {
		Vector row = board.getRow(rowNumber);
		Vector column = board.getColumn(colNumber);
		Area area = board.getAreaFor(rowNumber, colNumber);
		
		if(!row.vectorContainsNumber(i) &&
		   !column.vectorContainsNumber(i) &&
		   !area.containsNumber(i))
			return true;
		
		return false;
	}
}
